package java_thinking.unit_19;

/**
 * @Desc:   枚举理论 必看 https://blog.csdn.net/javazejian/article/details/71333103
 *      1.EnumSet是使用位向量实现的，什么是位向量呢？就是用一个位表示一个元素的状态，用一组位表示一个集合的状态，
 *        每个位对应一个元素，而状态只可能有两种。对于之前的枚举类Day，它有7个枚举值，一个Day的集合就可以用一个
 *        字节byte表示，最高位不用，设为0，最右边的位对应顺序最小的枚举值，从右到左，每位对应一个枚举值，1表示包
 *        含该元素，0表示不含该元素。
 *
 *      2.EnumSet是一个抽象类，它没有定义使用的向量长度，它有两个子类，RegularEnumSet和JumboEnumSet。
 *        RegularEnumSet使用一个long类型的变量作为位向量，long类型的位长度是64，re = 0101 0110 101....  一共64位
 *        JumboEnumSet使用一个long类型的数组。 re = [long1,long2,long3....]
 *        |------------|----------|----------|----------|----------|
 *        |
 *        |  数字范围      [0,63]     [64,127]  [128,191]    ...    |
 *        |------------|----------|----------|----------|----------|
 *        |
 *        | long数组索引      0         1           2         ...   |
 *        |------------|----------|----------|----------|----------|
 *        如果枚举值个数小于等于64，则静态工厂方法中创建的就是RegularEnumSet，大于64的话就是JumboEnumSet
 *
 *      3.静态工厂方法 | 工厂方法的原理与对比 ：https://blog.csdn.net/hzy38324/article/details/72630415
 *
 *      4.位向量 https://blog.csdn.net/panyongcsd/article/details/52641298
 *
 *      5.位向量表示集合
 *        a=[01101001]表示{0，3，5，6} 从右往左为 1 的位分别为 0、3、5、6 所以表示集合 {0，3，5，6}
 *        b=[01010101]表示{0，2，4，6} 从右往左为 1 的位分别为 0、2、4、6 所以表示集合 {0，2，4，6}
 *        a&b={01000001} 为 1 的位分比为 0、6 所以交集为 {0,6} 也就是 {0，3，5，6} 与 {0，2，4，6} 中共同存在 0 与 6 两个数字
 *
 *      6.volatile关键字，该关键字有两层语义。第一层语义是可见性，可见性是指在一个线程中对该变量的修改会马上由工作内存（Work
 *        Memory）写回主内存（Main Memory），所以其它线程会马上读取到已修改的值，关于工作内存和主内存可简单理解为高速缓存（直接
 *        与CPU打交道）和主存（日常所说的内存条），注意工作内存是线程独享的，主存是线程共享的。volatile的第二层语义是禁止指令重
 *        排序优化，我们写的代码（特别是多线程代码），由于编译器优化，在实际执行的时候可能与我们编写的顺序不同。编译器只保证程序
 *        执行结果与源代码相同，却不保证实际指令的顺序与源代码相同，这在单线程并没什么问题，然而一旦引入多线程环境，这种乱序就可
 *        能导致严重问题。volatile关键字就可以从语义上解决这个问题，值得关注的是volatile的禁止指令重排序优化功能在Java 1.5后才
 *        得以实现，因此1.5前的版本仍然是不安全的，即使使用了volatile关键字。
 *
 *      7.枚举与单例模式 https://blog.csdn.net/javazejian/article/details/71333103
 *        关于单例，我们总是应该记住：线程安全，延迟加载，序列化与反序列化安全，反射安全是很重要的
 *
 *      8.总结：
 *        枚举本质上是通过普通的类来实现的，只是编译器为我们进行了处理。每个枚举类型都继承自java.lang.Enum，并自动添加了values
 *        和valueOf方法。而每个枚举常量是一个静态常量字段，使用内部类实现，该内部类继承了枚举类。所有枚举常量都通过静态代码块来
 *        进行初始化，即在类加载期间就初始化。另外通过把clone、readObject、writeObject这三个方法定义为final的，同时实现是抛出
 *        相应的异常。这样保证了每个枚举类型及枚举常量都是不可变的。可以利用枚举的这两个特性来实现线程安全的单例。
 * @author: cww
 * @DateTime: 2019-05-25 11:13
 */

public class EnumTheory {
}
